<template>
  <el-card shadow="hover" class="mt-20">
    <el-form>
      <el-form-item label="属性名">
        <el-input
          placeholder="请输入属性名"
          class="attr-input"
          v-model="attrData.attrName"
        />
      </el-form-item>
      <el-form-item>
        <!-- 属性名输入框没值，禁用添加属性按钮 -->
        <el-button
          type="primary"
          :icon="Plus"
          :disabled="!attrData.attrName"
          @click="addAttrValue"
          >添加属性值</el-button
        >
        <el-table border class="mt-20" :data="attrData.attrValueList">
          <el-table-column
            type="index"
            label="序号"
            width="60"
            align="center"
          />
          <!-- input框和展示框的切换，通过插槽实现 -->
          <el-table-column label="属性值名称">
            <template v-slot="{ row, $index }">
              <!-- v-show隐藏的原理是设置display:none，隐藏的输入框还在，input绑定的ref名称相同，导致同名覆盖，只有最后一个input能获取焦点 -->
              <!-- 解决方式：v-if，隐藏时input被卸载了 -->
              <el-input
                size="small"
                v-if="row.isShowEdit"
                ref="inputRef"
                v-model="row.valueName"
                @blur="switchAttrList(row, $index)"
                @keyup.enter="switchAttrList(row, $index)"
              ></el-input>
              <div v-else @click="switchInput(row)">
                {{ row.valueName }}
              </div>
            </template>
          </el-table-column>
          <el-table-column label="操作">
            <template v-slot="{ row, $index }">
              <!-- 
                多种让 Popconfirm 出现的方法
                @confirm="confirmEvent"
                @cancel="cancelEvent"
               -->
              <el-popconfirm
                confirm-button-text="Yes"
                cancel-button-text="No"
                :icon="InfoFilled"
                icon-color="#626AEF"
                :title="`您确定要删除 ${row.valueName} 吗?`"
                @confirm="delAttrValue($index)"
              >
                <template #reference>
                  <el-button
                    type="danger"
                    size="small"
                    :icon="Delete"
                    title="Delete"
                  ></el-button>
                </template>
              </el-popconfirm>
            </template>
          </el-table-column>
        </el-table>
      </el-form-item>
      <el-form-item>
        <el-button
          type="primary"
          :disabled="isDisabled"
          @click="updateOrAddAttr"
          >保存</el-button
        >
        <el-button @click="handleCancel">取消</el-button>
      </el-form-item>
    </el-form>
  </el-card>
</template>

<script lang="ts">
export default {
  name: "AddOrUpdateAttr",
};
</script>

<script lang="ts" setup>
import { Plus, Delete, InfoFilled } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
import { ref, reactive, nextTick, computed } from "vue";
import type { AttrItem, AttrValueItem } from "@/api/product/model/attrModel";
import { useAttrStore } from "@/stores/attr";
import { useCategoryStore } from "@/stores/category";
import { UpdateOrAddAttrValueListApi } from "@/api/product/attr";
// 接收父组件的自定义事件
const emit = defineEmits(["setShowAttrList"]);

// 点击取消按钮，显示属性列表 [实际还是改变父组件中isShowAttrList的值]
const handleCancel = () => {
  // 调用自定义事件，子组件给父组件传递数据
  emit("setShowAttrList", true);
};

// 引用store中的数据
const attrStore = useAttrStore();
const categoryStore = useCategoryStore();

// 定义表单的数据
const attrData = reactive<AttrItem>({
  attrName: attrStore.attrItem.attrName,
  attrValueList: attrStore.attrItem.attrValueList,
});

console.log(attrData);

// 定义表单的ref
const inputRef = ref();

// 点击添加属性按钮触发的回调
const addAttrValue = async () => {
  // table添加数据
  attrData.attrValueList.push({
    isShowEdit: true,
    valueName: "", // 收集属性名数据
  });
  // 数据更新是同步，页面更新是异步
  await nextTick();
  // 页面一渲染，就让input获得焦点
  inputRef.value.focus();
};

// input框失去焦点，切换回显示属性列表
const switchAttrList = (row: AttrValueItem, index: number) => {
  // 如果输入框没有输入内容，则删除这行数据，利用$index定位
  if (!row.valueName) {
    attrData.attrValueList.splice(index, 1);
    return;
  }
  // 判断输入内容是否重复
  const isRepeated = attrData.attrValueList.some((attrValue) => {
    if (attrValue === row) return;
    if (attrValue.valueName === row.valueName) return true;
    return false;
  });
  // 如果内容重复，就提示用户，并且不会切换回显示模式
  if (isRepeated) {
    ElMessage.warning("请勿输入重复的属性值");
    return;
  }
  // 将isShowEdit改为false
  row.isShowEdit = false;
};

// 显示属性列表模式，切换为input框输入模式，同时输入框获取焦点
const switchInput = async (row: AttrValueItem) => {
  // 将isShowEdit改为true
  row.isShowEdit = true;
  // 因为v-if input输入框会重新渲染，应该等渲染完成以后再让input获得焦点
  await nextTick();
  // // 页面一渲染，就让input获得焦点
  // inputRef.value.focus();
  inputRef.value.focus();
};

// 点击删除按钮触发回调
const delAttrValue = (index: number) => {
  // table删除数据
  attrData.attrValueList.splice(index, 1);
};

// 保存按钮禁用属性
// 采用计算属性，根据已有的数据 得到新的值
const isDisabled = computed(() => {
  return !(
    attrData.attrName &&
    attrData.attrValueList.some((attrValue) => attrValue.valueName)
  );
});

// 点击保存按钮触发回调
const updateOrAddAttr = async () => {
  const { attrName, attrValueList } = attrData;
  const { category3Id } = categoryStore;
  const { id } = attrStore.attrItem;
  await UpdateOrAddAttrValueListApi({
    attrName,
    attrValueList,
    categoryId: category3Id,
    categoryLevel: 3,
    id,
  });
  // 提示添加属性成功
  ElMessage.success(`${id ? "修改" : "添加"}属性成功！`);

  // // 调用自定义事件，子组件给父组件传递数据
  // emit("setShowAttrList", true);

  // 可以复用取消按钮的逻辑，直接调用取消的回调
  handleCancel();
};
</script>

<style scoped>
.attr-input {
  width: 250px;
}
</style>
